package com.demo.validation;

import com.demo.annotation.ValidPassword;
import org.passay.PasswordData;
import org.passay.PasswordValidator;
import org.passay.RuleResult;
import org.passay.WhitespaceRule;
import org.passay.spring.SpringMessageResolver;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;

/**
 * @author wangfengchen
 */
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, String> {

  // 注意：需要在 WebMvcConfig 中配置
  @Autowired
  private SpringMessageResolver messageResolver;

  @Override
  public boolean isValid(String password, ConstraintValidatorContext context) {
    // 配置消息国际化
    PasswordValidator passwordValidator = new PasswordValidator(messageResolver, Arrays.asList(
        // 长度规则：8 - 30 位
//        new LengthRule(6, 12),
//        // 至少有一个大写字母
//        new CharacterRule(EnglishCharacterData.UpperCase, 1),
//        // 至少有一个小写字母
//        new CharacterRule(EnglishCharacterData.LowerCase, 1),
        // 至少有一个数字
//        new CharacterRule(EnglishCharacterData.Digit, 1),
        // 至少有一个特殊字符
//        new CharacterRule(EnglishCharacterData.Special, 1),
        // 不允许连续 3 个字母，按字母表顺序
        // alphabetical is of the form 'abcde', numerical is '34567', qwery is 'asdfg'
        // the false parameter indicates that wrapped sequences are allowed; e.g. 'xyzabc'
//        new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
        // 不允许 3 个连续数字
//        new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
        // 不允许 QWERTY 键盘上的三个连续相邻的按键所代表的字符
//        new IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
        // 不允许包含空格
        new WhitespaceRule()));
    RuleResult ruleResult = passwordValidator.validate(new PasswordData(password));
    if (ruleResult.isValid()) {
      return true;
    }
    // 如果验证失败则将默认的禁用掉
    context.disableDefaultConstraintViolation();
    // 将错误信息连接在一起返回
    context.buildConstraintViolationWithTemplate(String.join("", passwordValidator.getMessages(ruleResult))).addConstraintViolation();
    return false;
  }
}
